package cn.chench.util;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

/**
 *线程执行工具类
* @author chencaihui 
* @datetime 创建时间：2017年3月21日 下午10:14:58 
*/
public class ThreadPoolUtil {

	/**可变尺寸的线程池 */
	private static ExecutorService cachedThreadPool = null;
	/**定时任务线程池*/
	private static ScheduledExecutorService scheduledService = null;
	/**单任务线程池 */
	private static ExecutorService singleThreadExecutor = null;
	/**池中所保存的线程数，包括空闲线程*/
	private static final int corePoolSize = 100;
	/**可以手动取消定时任务*/
	private static Map<String, ScheduledFuture<?>> scheduledMap = new HashMap<String, ScheduledFuture<?>>();
	/**允许最大并发量*/
	//private static final Semaphore sp = new Semaphore(10000);
	///sp.acquire();获取线程执行权限
	//sp.release();执行完释放线程
	
	/**
	 * 获取可变尺寸的线程池 
	 *@author chencaihui 
	 *@datetime 创建时间：2017年3月22日 上午8:52:46 
	 * @return
	 */
	private synchronized static final ExecutorService getCachedThreadPool(){
		if(cachedThreadPool==null || cachedThreadPool.isShutdown()){
			cachedThreadPool = Executors.newCachedThreadPool();
		}
		return cachedThreadPool;
	}
	
	/**
	 * 获取定时任务线程池
	 *@author chencaihui 
	 *@datetime 创建时间：2017年3月22日 上午8:52:46 
	 * @return
	 */
	private synchronized static final ScheduledExecutorService getScheduledThreadPool(){
		if(scheduledService==null || scheduledService.isShutdown()){
			scheduledService = Executors.newScheduledThreadPool(corePoolSize);
		}
		return scheduledService;
	}
	
	/**
	 * 获取单任务线程池 
	 *@author chencaihui 
	 *@datetime 创建时间：2017年3月22日 上午8:52:46 
	 * @return
	 */
	private synchronized static final ExecutorService getSingleThreadExecutor(){
		if(singleThreadExecutor==null || singleThreadExecutor.isShutdown()){
			singleThreadExecutor = Executors.newSingleThreadExecutor();
		}
		return singleThreadExecutor;
	}
	
	
	/**
	 * 执行线程
	 * @param command 线程任务
	 */
	public synchronized static void execute(Runnable command){
		getCachedThreadPool().execute(command);
	}
	
	/**
	 * 执行线程,等线程执行完返回执行结果（同步）
	 * @param command 线程任务
	 * @param result 返回结果
	 * @throws ExecutionException 
	 * @throws InterruptedException 
	 */
	/*public synchronized static boolean submit(Callable<Boolean> callable){
		try {
			Future<Boolean> future = getCachedThreadPool().submit(callable);
			while(!future.isDone()){
				Thread.sleep(300);
			}
			return future.get();
		} catch (InterruptedException | ExecutionException e) {
			LoggerUtil.error("执行线程异常", e);
		}
		return Boolean.FALSE;
	}*/
	
	/**
	 * 执行线程
	 * @param command 线程任务
	 */
	public synchronized static void executeSingle(Runnable command){
		getSingleThreadExecutor().execute(command);
	}
	
	/**
	 * 执行线程,等线程执行完返回执行结果（同步）
	 * @param callable 线程任务
	 * @throws ExecutionException 
	 * @throws InterruptedException 
	 * @return 返回结果
	 */
	/*public synchronized static boolean submitSingle(Callable<Boolean> callable){
		try {
			Future<Boolean> future = getSingleThreadExecutor().submit(callable);
			while(!future.isDone()){
				Thread.sleep(300);
			}
			return future.get();
		} catch (InterruptedException | ExecutionException e) {
			LoggerUtil.error("执行线程异常", e);
		}
		return Boolean.FALSE;
	}*/
	
	/**
	 * 延迟delay时间后开始执行command
	 * @param command 线程任务
	 * @param delay 延迟时间值
	 * @param timeUnit 时间单位
	 */
	public synchronized static void schedule(String key, Runnable command, long delay, TimeUnit timeUnit){
		ScheduledFuture<?> scheduledFuture = getScheduledThreadPool().schedule(command, delay, timeUnit);
		scheduledMap.put(key, scheduledFuture);
	}
	
	/**
	 * 延迟initialDelay时间后开始执行command，
	 * 并且按照period时间周期性重复调用
	 * （周期时间包括command运行时间，如果周期时间比command运行时间断，则command运行完毕后，立刻重复运行）
	 * @param command 线程任务
	 * @param initialDelay 开始执行时长
	 * @param period 运行周期时长
	 * @param timeUnit 时间单位
	 */
	public synchronized static void scheduleAtFixedRate(String key, Runnable command, long initialDelay, long period, TimeUnit timeUnit){
		ScheduledFuture<?> scheduledFuture = getScheduledThreadPool().scheduleAtFixedRate(command, initialDelay, period, timeUnit);
		scheduledMap.put(key, scheduledFuture);
	}
	
	/**
	 * 延迟initialDelay时间后开始执行command，
	 * 并且按照period时间周期性重复调用，
	 * 并且保证在上次运行完后才会执行下一次
	 * （周期时间不包括command运行时间）
	 * @param command 线程任务
	 * @param initialDelay 开始执行时长
	 * @param delay 运行周期时长
	 * @param timeUnit 时间单位
	 */
	public synchronized static void scheduleWithFixedDelay(String key, Runnable command, long initialDelay, long period, TimeUnit timeUnit){
		ScheduledFuture<?> scheduledFuture = getScheduledThreadPool().scheduleWithFixedDelay(command, initialDelay, period, timeUnit);
		scheduledMap.put(key, scheduledFuture);
	}

	/**
	 * 执行定时器线程,等线程执行完返回执行结果（同步）
	 * @param callable 线程任务
	 * @param delay 延迟时间值
	 * @param timeUnit （delay的单位）时间单位
	 * @return 返回结果
	 */
	/*public synchronized static boolean schedule(Callable<Boolean> callable, long delay, TimeUnit timeUnit){
		try {
			ScheduledFuture<Boolean> scheduledFuture = getScheduledThreadPool().schedule(callable, delay, timeUnit);
			while(!scheduledFuture.isDone()){
				Thread.sleep(300);
			}
			return scheduledFuture.get();
		} catch (Exception e) {
			LoggerUtil.error("执行定时任务线程异常", e);
		}
		return Boolean.FALSE;
	}*/
	
	/**
	 * 取消指定的定时任务
	 *@author chencaihui 
	 *@datetime 创建时间：2017年3月23日 下午10:28:28 
	 * @param key
	 */
	public static void cancelScheduled(String key){
		if(scheduledMap.containsKey(key))
			scheduledMap.get(key).cancel(true);
	}
	
	/**
	 * 关闭所有定时任务
	 *@author chencaihui 
	 *@datetime 创建时间：2017年3月31日 下午3:47:16
	 */
	public static void cancelAll(){
		if(NullUtil.isNotNull(scheduledMap)){
			Iterator<String> its = scheduledMap.keySet().iterator();
			while(its.hasNext()){
				scheduledMap.get(its.next()).cancel(true);
			}
			scheduledMap.clear();
		}
	}
	
	/**
	 * 关闭定时任务线程
	 *@author chencaihui 
	 *@datetime 创建时间：2017年3月23日 下午7:58:27
	 */
	public static void shutdownScheduled(){
		if(!getScheduledThreadPool().isShutdown())
			getScheduledThreadPool().shutdown();
	}
	
	/**
	 * 关闭可变无界线程
	 *@author chencaihui 
	 *@datetime 创建时间：2017年3月23日 下午7:58:07
	 */
	public static void shutdownCachedThread(){
		if(!getCachedThreadPool().isShutdown())
			getCachedThreadPool().shutdown();
	}
	
	/**
	 * 关闭单任务线程
	 *@author chencaihui 
	 *@datetime 创建时间：2017年3月23日 下午7:57:54
	 */
	public static void shutdownSingleThread(){
		if(!getSingleThreadExecutor().isShutdown())
			getSingleThreadExecutor().shutdown();
	}
	
	/**
	 * 关闭所有线程
	 *@author chencaihui 
	 *@datetime 创建时间：2017年3月23日 下午7:57:41
	 */
	public static void shutdownAll(){
		shutdownScheduled();
		shutdownCachedThread();
		shutdownSingleThread();
	}
}